#!/usr/bin/env python3
# map/obstacle_editor.py
# 障碍物编辑对话框
from PyQt5.QtWidgets import (
    QDialog,
    QLabel,
    QVBoxLayout,
    QHBoxLayout,
    QPushButton,
    QSlider,
    QLabel as SizeLabel,
)
from PyQt5.QtGui import QPixmap, QImage, QPainter, QPen, QBrush, QColor
from PyQt5.QtCore import Qt, QTimer
import numpy as np
import cv2
import pickle

import logging

logger = logging.getLogger(__name__)


class ObstacleEditor(QDialog):
    def __init__(self, map_manager, parent=None):
        super().__init__(parent)
        self.map_manager = map_manager
        self.setWindowTitle("地图编辑 - 添加/擦除障碍物")
        self.setModal(True)
        self.setGeometry(200, 200, 1200, 900)

        # 布局
        layout = QVBoxLayout(self)

        # 地图显示
        self.canvas = QLabel()
        self.canvas.setMinimumSize(1100, 700)
        self.canvas.setAlignment(Qt.AlignCenter)
        self.canvas.setStyleSheet("border: 1px solid black;")
        layout.addWidget(self.canvas)

        # 刷子大小控制
        self.brush_size = 100
        brush_layout = QHBoxLayout()
        brush_label = QLabel("刷子大小:")
        self.brush_slider = QSlider(Qt.Horizontal)
        min_size = 1
        max_size = min(self.map_manager.map_width, self.map_manager.map_height) // 4
        self.brush_slider.setRange(min_size, max_size)
        self.brush_slider.setValue(self.brush_size)
        self.brush_slider.valueChanged.connect(self.update_brush_size)
        self.size_label = SizeLabel(str(self.brush_size))
        brush_layout.addWidget(brush_label)
        brush_layout.addWidget(self.brush_slider)
        brush_layout.addWidget(self.size_label)
        layout.addLayout(brush_layout)

        # 按钮布局
        btn_layout = QHBoxLayout()
        self.confirm_btn = QPushButton("确认 (Enter)")
        self.confirm_btn.clicked.connect(self.confirm_and_close)
        self.save_btn = QPushButton("保存")
        self.save_btn.clicked.connect(self.save_preset_and_close)
        self.load_preset_btn = QPushButton("加载预设")
        self.load_preset_btn.clicked.connect(self.load_preset)
        self.cancel_btn = QPushButton("取消 (Esc/Q)")
        self.cancel_btn.clicked.connect(self.reject)
        btn_layout.addWidget(self.confirm_btn)
        btn_layout.addWidget(self.save_btn)
        btn_layout.addWidget(self.load_preset_btn)
        btn_layout.addWidget(self.cancel_btn)
        layout.addLayout(btn_layout)

        # 鼠标事件
        self.canvas.setMouseTracking(True)
        self.canvas.mousePressEvent = self.mouse_press
        self.canvas.mouseMoveEvent = self.mouse_move
        self.canvas.mouseReleaseEvent = self.mouse_release

        # 绘制状态
        self.drawing = False
        self.last_pos = None
        # 加载现有的障碍层
        self.obstacle_layer = self.map_manager.get_obstacle_layer().copy()
        self.update_canvas()

        # 键盘事件
        self.keyPressEvent = self.key_press

        # 更新定时器
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_canvas)
        self.timer.start(50)

    def update_brush_size(self, value):
        self.brush_size = value
        self.size_label.setText(str(value))

    def key_press(self, event):
        key = event.key()
        if key == Qt.Key_Escape or key == Qt.Key_Q:
            self.reject()
        elif key == Qt.Key_Return or key == Qt.Key_Enter:
            self.confirm_and_close()
        elif key == Qt.Key_X:  # 减小刷子
            self.brush_size = max(1, self.brush_size - 5)
            self.brush_slider.setValue(self.brush_size)
        elif key == Qt.Key_C:  # 增大刷子
            max_size = min(self.map_manager.map_width, self.map_manager.map_height) // 4
            self.brush_size = min(max_size, self.brush_size + 5)
            self.brush_slider.setValue(self.brush_size)

    def load_preset(self):
        if self.map_manager.load_next_preset():
            self.obstacle_layer = self.map_manager.get_obstacle_layer().copy()
            self.update_canvas()
            logger.info("预设障碍层加载成功")

    def confirm_and_close(self):
        self.map_manager.set_obstacle_layer(self.obstacle_layer)
        self.map_manager.apply_obstacles()
        self.accept()

    def save_preset_and_close(self):
        self.map_manager.set_obstacle_layer(self.obstacle_layer)
        self.map_manager.save_current_preset()
        self.map_manager.apply_obstacles()
        self.accept()

    def mouse_press(self, event):
        map_pos = self.pos_to_map(event.pos())
        if map_pos is None:
            return
        self.drawing = True
        self.last_pos = map_pos
        add = event.button() == Qt.LeftButton
        self.draw_circle(map_pos, add)

    def mouse_move(self, event):
        if not self.drawing:
            return
        map_pos = self.pos_to_map(event.pos())
        if map_pos is None or self.last_pos is None:
            return
        left_pressed = bool(event.buttons() & Qt.LeftButton)
        right_pressed = bool(event.buttons() & Qt.RightButton)
        if left_pressed or right_pressed:
            add = left_pressed
            self.draw_line(self.last_pos, map_pos, add)
            self.last_pos = map_pos

    def mouse_release(self, event):
        self.drawing = False
        self.last_pos = None

    def draw_circle(self, pos, add):
        mx, my = map(int, pos)
        temp = np.zeros_like(self.obstacle_layer)
        radius = max(1, self.brush_size // 4)
        cv2.circle(temp, (mx, my), radius, 255, -1)
        mask = temp > 0
        if add:
            self.obstacle_layer[mask] = 255
        else:
            self.obstacle_layer[mask] = 0
        self.update_canvas()

    def draw_line(self, start, end, add):
        mx1, my1 = map(int, start)
        mx2, my2 = map(int, end)
        temp = np.zeros_like(self.obstacle_layer)
        thickness = max(1, self.brush_size // 2)
        cv2.line(temp, (mx1, my1), (mx2, my2), 255, thickness=thickness)
        mask = temp > 0
        if add:
            self.obstacle_layer[mask] = 255
        else:
            self.obstacle_layer[mask] = 0
        self.update_canvas()

    def pos_to_map(self, pos):
        if self.map_manager.map_image is None:
            return None
        canvas_size = self.canvas.size()
        map_width = self.map_manager.map_width
        map_height = self.map_manager.map_height
        # 计算缩放比例以保持宽高比
        scale_x = canvas_size.width() / map_width
        scale_y = canvas_size.height() / map_height
        scale = min(scale_x, scale_y)
        # 计算缩放后图像尺寸
        scaled_w = map_width * scale
        scaled_h = map_height * scale
        # 计算偏移
        offset_x = (canvas_size.width() - scaled_w) / 2
        offset_y = (canvas_size.height() - scaled_h) / 2
        # 检查是否在图像区域内
        if (
            pos.x() < offset_x
            or pos.x() > offset_x + scaled_w
            or pos.y() < offset_y
            or pos.y() > offset_y + scaled_h
        ):
            return None
        # 转换为地图坐标 (x: 列, y: 行)
        map_x = int((pos.x() - offset_x) / scaled_w * map_width)
        map_y = int((pos.y() - offset_y) / scaled_h * map_height)
        if 0 <= map_x < map_width and 0 <= map_y < map_height:
            return (map_x, map_y)
        return None

    def update_canvas(self):
        if self.map_manager.map_image is None:
            return
        # 合并底图和障碍层
        combined = self.map_manager.map_image.copy()
        obstacle_mask = self.obstacle_layer > 0
        combined[obstacle_mask] = [0, 255, 0]  # BGR 绿色

        # QImage
        h, w = combined.shape[:2]
        qimg = QImage(combined.data, w, h, w * 3, QImage.Format_RGB888)
        qimg = qimg.rgbSwapped()
        pixmap = QPixmap.fromImage(qimg).scaled(
            self.canvas.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation
        )
        self.canvas.setPixmap(pixmap)
